package com.example.blueconn.utils;

import androidx.annotation.Nullable;

import com.example.blueconn.BuildConfig;
import com.example.blueconn.data.FxData;
import com.example.blueconn.data.LightData;
import com.example.blueconn.data.TempData;
import com.example.blueconn.manager.ActivityMgr;
import com.example.blueconn.manager.DataMgr;
import com.example.blueconn.manager.FastBleManager;
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog;

/**
 * Created by zhudongao
 * Desc
 * Date 2020/7/15
 */

public class DataUtils {

    private static final String TAG = "DataUtils";
    /**
     * 用于建立十六进制字符的输出的大写字符数组
     */
    private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    /**
     * 开启校准模式
     */
    public static String openCorrectCmd = "AA00A3FFFFFF";
    /**
     * 关闭校准模式
     */
    public static String closeCorrectCmd = "AA00A4FFFFFF";

    /*****************设备加入**********************/
    private static String frameEnd = "FFFFFF";

    private static String getNum(int num) {
        String data;
        if (num > 0 && num < 10) {
            data = "0" + num;
        } else {
            data = String.valueOf(num);
        }
        return data;
    }

    /**
     * 字符串转换为hexString
     *
     * @param data 原始数据
     * @return hexString
     */
    public static String toHexString(String data) {
        if (data == null || data.isEmpty()) {
            return "";
        }
        byte[] bytes = data.getBytes();
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            sb.append(Integer.toHexString(aByte));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 16进制字符串转 java字符串
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        hexStr = hexStr.replace(" ", "");
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

    //byte转 16进制字符
    public static String bytesToHexString(byte[] data, int len) {
        if (data == null || data.length <= 0 || len <= 0) {
            return "";
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < len; i++) {
            int v = data[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data byte[]
     * @return 十六进制String
     */
    public static String encodeHexStr(byte[] data, int len) {
        return new String(encodeHex(data, DIGITS_UPPER, len));
    }

    private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];

        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }

        return new String(hexChars);
    }

    //byte数组转换为16进制char
    public static char[] encodeHex(byte[] data, char[] toDigits, int len) {
        int l = data.length;
        if (l > len) {
            l = len;
        }
        char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }

    /**
     * 16进制String 转 bytes
     */
    public static byte[] hexToBytes(String hex) {
        hex = hex.length() % 2 != 0 ? "0" + hex : hex;

        byte[] b = new byte[hex.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(hex.substring(index, index + 2), 16);
            b[i] = (byte) v;
        }
        return b;
    }

    /**
     * 将十六进制字符数组转换为字节数组
     * 十六进制 字符数组：String.toCharArray()
     *
     * @param data 十六进制char[]
     * @return byte[]
     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
     */
    public static byte[] decodeHex(char[] data) {

        int len = data.length;

        if ((len & 0x01) != 0) {
            throw new RuntimeException("Odd number of characters.");
        }

        byte[] out = new byte[len >> 1];

        // two characters form the hex value.
        for (int i = 0, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }

        return out;
    }

    public static float hexStr2Float(String data) {
//        float fData = Float.intBitsToFloat(new BigInteger(data, 16).intValue());
//        return fData;
//        BigDecimal bigDecimal = new BigDecimal(fData);
//        return bigDecimal.setScale(3, BigDecimal.ROUND_HALF_UP).floatValue();
        try {
            String str = DataUtils.hexStr2Str(data);
            if (str.trim().isEmpty()) {
                return 0;
            }
            return Float.parseFloat(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 将十六进制字符转换成一个整数
     *
     * @param ch    十六进制char
     * @param index 十六进制字符在字符数组中的位置
     * @return 一个整数
     * @throws RuntimeException 当ch不是一个合法的十六进制字符时，抛出运行时异常
     */
    protected static int toDigit(char ch, int index) {
        int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new RuntimeException("Illegal hexadecimal character " + ch
                    + " at index " + index);
        }
        return digit;
    }

    /*******************校准**************************/


    /*****************读数据*************************/

    /**
     * 开启检测模式
     */
    public static byte[] openDetectMode() {
        return hexToBytes("DDB1CCCFCCCC");
    }

    /**
     * 开启温度检测模式
     */
    public static byte[] openTempMode() {
        return hexToBytes("DDB2CCCFCCCC");
    }

    public static byte[] xishuOk() {
        return hexToBytes("DDB4CCCFCCCC");
    }

    /**
     * 重启设备
     */
    public static byte[] rebootDevice() {
        return hexToBytes("DDA3CCCFCCCC");
    }


    /*******************数据解析******************************/

    /**
     * 获取解析后的实时数据
     */
    @Nullable
    public static void getResult(String data) {
        //清理hexString中的空格
        String newData = data.replace(" ", "").toUpperCase();
        if (StringUtils.isEmpty(newData)) {
            return;
        }
        //todo 做分割处理，防止出现多个数据拼接一块的情况
        //在此处进行校验，提示状态校验 todo 这块可以抽取出去
        boolean isMatched = DataUtils.resultDataDeal(newData);
        if (!isMatched) {
            //处理前必须做拦截，剔除掉命令指令等。
            generateDataBean(newData);
        }
    }

    private static void doCalculateLight(LightData lightData, float ac, int index, boolean isHigh, boolean isFirst) {
        FxData fxData = DataMgr.getLightFxMap().get(index);
        if (fxData != null) {
            float data;
            if (isHigh) {
                data = fxData.slopB * ac + fxData.nodalB;
            } else {
                data = fxData.slopA * ac + fxData.nodalA;
            }
            if (data < 0) {
                data = 0;
            }
            float result = (int) (data * 10) / 10f;
            switch (index) {
                case 1:
                    if (isFirst) {
                        lightData.lightA1 = result;
                    } else {
                        lightData.lightA2 = result;
                    }
                    break;
                case 2:
                    if (isFirst) {
                        lightData.lightB1 = result;
                    } else {
                        lightData.lightB2 = result;
                    }
                    break;
                case 3:
                    if (isFirst) {
                        lightData.lightC1 = result;
                    } else {
                        lightData.lightC2 = result;
                    }
                    break;
                case 4:
                    if (isFirst) {
                        lightData.lightD1 = result;
                    } else {
                        lightData.lightD2 = result;
                    }
                    break;
                case 5:
                    if (isFirst) {
                        lightData.lightE1 = result;
                    } else {
                        lightData.lightE2 = result;
                    }
                    break;
                case 6:
                    if (isFirst) {
                        lightData.lightF1 = result;
                    } else {
                        lightData.lightF2 = result;
                    }
                    break;
                default:
                    break;
            }
        }
    }

    private static void doCalculateTemp(TempData tempData, float ac, int index) {
        FxData fxData = DataMgr.getTempFxMap().get(index);
        if (fxData != null) {
            float data = fxData.slopA * ac + fxData.nodalA;
            if (data < 0) {
                data = 0;
            }
            float result = (int) (data * 100) / 100f;
            switch (index) {
                case 1:
                    tempData.temp1 = result;
                    break;
                case 2:
                    tempData.temp2 = result;
                    break;
                case 3:
                    tempData.temp3 = result;
                    break;
                case 4:
                    tempData.temp4 = result;
                    break;
                case 5:
                    tempData.temp5 = result;
                    break;
                default:
                    break;
            }
        }
    }

    private static LightData lightData = new LightData();
    private static TempData tempData = new TempData();

    //生成dataBean
    private static void generateDataBean(String data) {
        try {
            if (data.startsWith("DDFF") || data.startsWith("DDBB")) {
                String groupType = data.substring(2, 4);
                boolean isFirst = true;
                if ("BB".equals(groupType)) {
                    isFirst = false;
                }
                String modeType = data.substring(4,6);
                boolean isHigh = false;
                if ("F1".equals(modeType)) {
                    isHigh = true;
                }

                float lAc1 = Long.parseLong(data.substring(6, 10), 16);
                doCalculateLight(lightData, lAc1, 1, isHigh, isFirst);
                float lAc2 = Long.parseLong(data.substring(10, 14), 16);
                doCalculateLight(lightData, lAc2, 2, isHigh, isFirst);
                float lAc3 = Long.parseLong(data.substring(14, 18), 16);
                doCalculateLight(lightData, lAc3, 3, isHigh, isFirst);
                float lAc4 = Long.parseLong(data.substring(18, 22), 16);
                doCalculateLight(lightData, lAc4, 4, isHigh, isFirst);
                float lAc5 = Long.parseLong(data.substring(22, 26), 16);
                doCalculateLight(lightData, lAc5, 5, isHigh, isFirst);
                float lAc6 = Long.parseLong(data.substring(26, 30), 16);
                doCalculateLight(lightData, lAc6, 6, isHigh, isFirst);
                LightData clone = (LightData) lightData.clone();
                DataMgr.getRealLightData().postValue(clone);
//                DataMgr.sb.append("照度解析成功： ").append(clone.toString()).append("\n");
            } else if (data.startsWith("DDEE")){

                float tAc1 = Long.parseLong(data.substring(4, 8), 16);
                doCalculateTemp(tempData, tAc1, 1);
                float tAc2 = Long.parseLong(data.substring(8, 12), 16);
                doCalculateTemp(tempData, tAc2, 2);
                float tAc3 = Long.parseLong(data.substring(12, 16), 16);
                doCalculateTemp(tempData, tAc3, 3);
                float tAc4 = Long.parseLong(data.substring(16, 20), 16);
                doCalculateTemp(tempData, tAc4, 4);
                float tAc5 = Long.parseLong(data.substring(20, 24), 16);
                doCalculateTemp(tempData, tAc5, 5);
                TempData clone = (TempData) tempData.clone();
                DataMgr.getRealTempData().postValue(clone);
//                DataMgr.sb.append("温度解析成功： ").append(clone.toString()).append("\n");
            }
        } catch (Exception e) {
//            DataMgr.sb.append("数据解析异常： ").append(e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 产生随机数据
     */
    public static String randomLightOne() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int lightData = (((int) (Math.random() * 100) + 200));
            String data = Integer.toHexString(lightData);
            if (data.length() == 1) {
                data = "000" + data;
            } else if (data.length() == 2) {
                data = "00" + data;
            } else if (data.length() == 3) {
                data = "0" + data;
            }
            sb.append(data);
        }
        return "DDFFF0" + sb + "FF";
    }

    /**
     * 产生随机数据
     */
    public static String randomLightTwo() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int lightData = (((int) (Math.random() * 100) + 200));
            String data = Integer.toHexString(lightData);
            if (data.length() == 1) {
                data = "000" + data;
            } else if (data.length() == 2) {
                data = "00" + data;
            } else if (data.length() == 3) {
                data = "0" + data;
            }
            System.out.println(lightData + ": " + data);
            sb.append(data);
        }

        return "DDBBF0" + sb + "FF";
    }

    /**
     * 产生随机数据
     */
    public static String randomTemp() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 5; i++) {
            int lightData = (int) (Math.random() * 300);
            String data = Integer.toHexString(lightData);
            if (data.length() == 1) {
                data = "000" + data;
            } else if (data.length() == 2) {
                data = "00" + data;
            } else if (data.length() == 3) {
                data = "0" + data;
            }
            System.out.println(lightData + ": " + data);
            sb.append(data);
        }

        return "DDEE" + sb + "FF";
    }

    /************************设备操作处理****************************/
    public static boolean resultDataDeal(String data) {
        if (StringUtils.isEmpty(data)) {
            return false;
        }
        boolean isDeal = true;
        if (data.startsWith("DD3")) {
            convertLightFx(data);
        } else if (data.startsWith("DD4")) {
            convertTempFx(data);
        } else if (ResultData.LIGHT_VERIFY_OK.equals(data)) {
            DialogUtils.showTipDialog(ActivityMgr.getInstance().getCurrentActivity(),
                    QMUITipDialog.Builder.ICON_TYPE_SUCCESS,
                    "照度系数设置ok");
        } else if (ResultData.TEMP_VERIFY_OK.equals(data)) {
            DialogUtils.showTipDialog(ActivityMgr.getInstance().getCurrentActivity(),
                    QMUITipDialog.Builder.ICON_TYPE_SUCCESS,
                    "温度系数设置ok");
        } else if (ResultData.REBOOT_DEVICE_OK.equals(data)) {
            DialogUtils.showTipDialog(ActivityMgr.getInstance().getCurrentActivity(),
                    QMUITipDialog.Builder.ICON_TYPE_SUCCESS,
                    "设备已重启");
            FastBleManager.recon.postValue(true);
        } else {
            isDeal = false;
        }
        return isDeal;
    }

    private static void convertLightFx(String data) {
        try {
            int number = Integer.parseInt(data.substring(3, 4));
            FxData fxData = DataMgr.getLightFxDataByNumber(number);
            fxData.dataType = "L";
            fxData.number = number;
            String splitData;
            splitData = data.substring(22, 24);
            String slopRawData;
            String nodeRawData;
            if ("20".equals(splitData)) {
                slopRawData = data.substring(6, 22);
                nodeRawData = data.substring(24, 38);
            } else {
                String[] params = data.split("20");
                slopRawData = params[0].substring(6);
                int indexEnd = params[1].indexOf("FF");
                nodeRawData = params[1].substring(0, indexEnd);
            }

            String ltype = data.substring(4, 6);
            if ("31".equals(ltype)) {
                fxData.slopA = hexStr2Float(slopRawData);
                fxData.nodalA = hexStr2Float(nodeRawData);
            } else if ("32".equals(ltype)) {
                fxData.slopB = hexStr2Float(slopRawData);
                fxData.nodalB = hexStr2Float(nodeRawData);
            }
            DataMgr.getInstance().postFxData(fxData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void convertTempFx(String data) {
        try {
            int number = Integer.parseInt(data.substring(3, 4));
            FxData fxData = DataMgr.getTempFxDataByNumber(number);
            fxData.dataType = "T";
            fxData.number = number;
            String splitData = data.substring(20, 22);
            String slopRawData;
            String nodeRawData;
            if ("20".equals(splitData)) {
                slopRawData = data.substring(4, 20);
                nodeRawData = data.substring(22, 38);
            } else {
                String[] params = data.split("20");
                slopRawData = params[0].substring(4);
                int indexEnd = params[1].indexOf("FF");
                nodeRawData = params[1].substring(0, indexEnd);
            }
            fxData.slopA = hexStr2Float(slopRawData);
            fxData.nodalA = hexStr2Float(nodeRawData);

            DataMgr.getInstance().postFxData(fxData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回数据
     */
    public interface ResultData {
        String TEMP_VERIFY_OK = "DDFBBBFF";
        String LIGHT_VERIFY_OK = "DDFCBBFF";
        String REBOOT_DEVICE_OK = "DDFABBFF";
    }
}
